/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package PackageUpdater.Update;

import Interface.AVideoDownloader;
import Interface.IDownloadProgressEvent;
import Manager.DownloaderManager;
import PackageUpdater.Config.SysConfig;
import PackageUpdater.Config.UpdateFileEntry;
import PackageUpdater.Config.UpdateList;
import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author wcss
 */
public class JUpdateManager implements IDownloadProgressEvent {

    public static JUpdateManager manager = new JUpdateManager();
    private String configPath = "/etc/packageUpdater.cfg";
    private SysConfig configObj = null;
    private Hashtable<String, AVideoDownloader> taskList = new Hashtable<String, AVideoDownloader>();
    public String logTextFile = "";
    public String listXmlFile = "";
    private Queue<String> queueList = new LinkedList<String>();
    private ArrayList<UpdateList> updateEntryList = new ArrayList<UpdateList>();
    private IUpdateTaskProgressEvent updateDownloadEvent;
    private ArrayList<UpdateFileEntry> updateFileCopyList = new ArrayList<UpdateFileEntry>();
    private int downloadTaskBaseIndex = 0;

    public void loadConfig() throws Exception {
        if (new File(getConfigPath()).exists()) {
            setConfigObj(SysConfig.load(getConfigPath()));
        }
    }

    public String getDownloadBufferDir(String task) {
        File ff = new File(JAppToolKit.JRunHelper.getUserHomeDirPath() + "/.softwareupdatebuffers/" + task);
        ff.mkdirs();
        return ff.getAbsolutePath();
    }

    public void clearDownloadBuffers() throws Exception {
        if (new File(JAppToolKit.JRunHelper.getUserHomeDirPath() + "/.softwareupdatebuffers").exists()) {
            JAppToolKit.JRunHelper.runSysCmd("rm -rf " + JAppToolKit.JRunHelper.getUserHomeDirPath() + "/.softwareupdatebuffers");
        }

        new File(JAppToolKit.JRunHelper.getUserHomeDirPath() + "/.softwareupdatebuffers").mkdirs();
    }

    public void delDownloadBufferDir(String task) throws Exception {
        File ff = new File(JAppToolKit.JRunHelper.getUserHomeDirPath() + "/.softwareupdatebuffers/" + task);
        if (ff.exists()) {
            JAppToolKit.JRunHelper.runSysCmd("rm -rf " + ff.getAbsolutePath());
        }
    }

    public AVideoDownloader createTask(String task, String bufName, String url, Boolean isClearBuffer) throws Exception {
        if (isClearBuffer) {
            delDownloadBufferDir(bufName);
        }
        return DownloaderManager.manager.createDownloader(task, url, "http", getDownloadBufferDir(bufName), 0, 0, this);
    }

    public void delAllDownloadBufferDirs() throws Exception {
        Iterator i = taskList.entrySet().iterator();
        while (i.hasNext()) {
            Entry entry = (Entry) i.next();
            delDownloadBufferDir((String) entry.getKey());
        }
    }

    public void searchUpdate() throws Exception {
        if (getConfigObj() == null) {
            this.loadConfig();
        }

        if (getConfigObj() != null) {
            taskList.put("logUpdate", createTask("logUpdate", "updateList", this.getConfigObj().getUpdateLogUrl(), false));
            taskList.put("listUpdate", createTask("listUpdate", "updateList", this.getConfigObj().getUpdateListUrl(), false));
            DownloaderManager.manager.startDownloader("logUpdate");
        }
    }

    public UpdateList[] checkNeedUpdateEntrys() {
        UpdateList[] result = null;
        ArrayList<UpdateList> list = new ArrayList<UpdateList>();
        for (UpdateList entry : this.updateEntryList) {
            if (entry.getUpdateIndex() > this.getConfigObj().getNowUpdateIndex()) {
                list.add(entry);
            }
        }
        result = new UpdateList[list.size()];
        int indexx = 0;
        for (UpdateList obj : list) {
            result[indexx] = obj;
            indexx++;
        }
        return result;
    }

    public void clearTaskQueueData() {
        queueList.clear();
        taskList.clear();
        getUpdateFileCopyList().clear();
    }

    public void stopAllTask() throws Exception
    {
        DownloaderManager.manager.stopAllDownloader();
    }
    
    public void downloadUpdateEntry(UpdateList ul) throws Exception {
        if (ul != null && ul.getUpdateFiles() != null && ul.getUpdateFiles().length > 0 && queueList.size() <= 0) {
            for (UpdateFileEntry ufe : ul.getUpdateFiles()) {
                downloadTaskBaseIndex++;
                AVideoDownloader avds = createTask(downloadTaskBaseIndex + "%UFile", "updateFiles", ufe.getSource(), false);
                avds.tag = ufe.getDest();
                taskList.put(downloadTaskBaseIndex + "%UFile", avds);
                queueList.offer(downloadTaskBaseIndex + "%UFile");
            }

            startQueueDownload();
        } else {
            throw new Exception("sorry,queue is not empty.");
        }
    }

    @Override
    public void onReportProgress(AVideoDownloader avd, long current, long total) {
        if (this.updateDownloadEvent != null) {
            this.updateDownloadEvent.handleUpdateDownloading(this, avd.downloaderID, current, total);
        }
    }

    @Override
    public void onReportError(AVideoDownloader avd, String code, String msg) {
        if (this.updateDownloadEvent != null) {
            this.updateDownloadEvent.handleUpdateError(this, avd.downloaderID, msg);
        }
    }

    @Override
    public void onReportFinish(AVideoDownloader avd) {
        if (avd.downloaderID != null && avd.downloaderID.equals("logUpdate")) {
            logTextFile = avd.getVideoBufferUrl();
            try {
                DownloaderManager.manager.startDownloader("listUpdate");
            } catch (Exception ex) {
                Logger.getLogger(JUpdateManager.class.getName()).log(Level.SEVERE, null, ex);
                onReportError(avd, "download", ex.getMessage());
            }
        } else if (avd.downloaderID != null && avd.downloaderID.equals("listUpdate")) {
            listXmlFile = avd.getVideoBufferUrl();
            if (new File(listXmlFile).exists()) {
                try {
                    String[] team = JAppToolKit.JDataHelper.readAllLines(listXmlFile);
                    int indexx = 0;
                    for (String s : team) {
                        if (avd.isValidUrl(s)) {
                            indexx++;
                            AVideoDownloader avds = createTask(indexx + "%UIndex", "updateListFile", s, false);
                            taskList.put(indexx + "%UIndex", avds);
                            queueList.offer(indexx + "%UIndex");
                        }
                    }
                    
                    updateEntryList.clear();
                    this.startQueueDownload();                    
                } catch (Exception ex) {
                    Logger.getLogger(JUpdateManager.class.getName()).log(Level.SEVERE, null, ex);
                    onReportError(avd, "download", ex.getMessage());
                }

            }
        } else if (avd.downloaderID != null && avd.downloaderID.endsWith("%UIndex")) {
            try {
                updateEntryList.add(UpdateList.load(avd.getVideoBufferUrl()));
            } catch (Exception ex) {
                Logger.getLogger(JUpdateManager.class.getName()).log(Level.SEVERE, null, ex);
                onReportError(avd, "download", ex.getMessage());
            }

            if (queueList.size() > 0) {
                try {
                    this.startQueueDownload();
                } catch (Exception ex) {
                    Logger.getLogger(JUpdateManager.class.getName()).log(Level.SEVERE, null, ex);
                    onReportError(avd, "download", ex.getMessage());
                }
            } else {
                if (this.updateDownloadEvent != null) {
                    this.updateDownloadEvent.handleUpdateList(this, null);
                }
            }
        } else if (avd.downloaderID != null && avd.downloaderID.endsWith("%UFile")) {
            getUpdateFileCopyList().add(new UpdateFileEntry(avd.getVideoBufferUrl(), avd.tag.toString()));
            if (queueList.size() > 0) {
                try {
                    this.startQueueDownload();
                } catch (Exception ex) {
                    Logger.getLogger(JUpdateManager.class.getName()).log(Level.SEVERE, null, ex);
                    onReportError(avd, "download", ex.getMessage());
                }
            } else {
                if (this.getUpdateDownloadEvent() != null) {
                    this.getUpdateDownloadEvent().handleUpdateFiles(this, avd.downloaderID);
                }
            }
        }
    }

    @Override
    public void onReportStatus(AVideoDownloader avd, String state) {
    }

    /**
     * @return the configPath
     */
    public String getConfigPath() {
        return configPath;
    }

    /**
     * @param configPath the configPath to set
     */
    public void setConfigPath(String configPath) {
        this.configPath = configPath;
    }

    /**
     * @return the configObj
     */
    public SysConfig getConfigObj() {
        return configObj;
    }

    /**
     * @param configObj the configObj to set
     */
    public void setConfigObj(SysConfig configObj) {
        this.configObj = configObj;
    }

    private void startQueueDownload() throws Exception {
        if (queueList.size() > 0) {
            String name = queueList.poll();
            DownloaderManager.manager.startDownloader(name);
        }
    }

    /**
     * @return the updateDownloadEvent
     */
    public IUpdateTaskProgressEvent getUpdateDownloadEvent() {
        return updateDownloadEvent;
    }

    /**
     * @param updateDownloadEvent the updateDownloadEvent to set
     */
    public void setUpdateDownloadEvent(IUpdateTaskProgressEvent updateDownloadEvent) {
        this.updateDownloadEvent = updateDownloadEvent;
    }

    /**
     * @return the updateFileCopyList
     */
    public ArrayList<UpdateFileEntry> getUpdateFileCopyList() {
        return updateFileCopyList;
    }

    /**
     * @param updateFileCopyList the updateFileCopyList to set
     */
    public void setUpdateFileCopyList(ArrayList<UpdateFileEntry> updateFileCopyList) {
        this.updateFileCopyList = updateFileCopyList;
    }
}
